vector<int> client_fds;
RoomManager room_manager;
bool server_running = 1;
int global_server_fd = 1;

void handle_sigint()
{
    cout << "Server caught shutdown..." <<endl;
    if(global_server_fd == -1) close(global_server_fd);
    cout << "\033[0m" << flush;
    log_to_file("Server shutdown by SIGINT.\n");
    exit(0);
}

void broadcast(int sender_fd, const string& msg, bool include_room_prefix = true)
{
    string room = room_manager.get_user_room(sender_fd);
    string prefix = include_room_prefix ? "[" + room + "]" : "";
    for(auto fd : client_fds)
    {
        if(fd != sender_fd && room_manager.get_user_room(fd) == room)
        {
            string ful_msg = prefix + msg;
            send(fd, ful_msg.c_str(), ful_msg.size(), 0);
        }
    }
}

void handle_message(int fd, const string& msg, fd_set& all_set, size_t& i)
{
    if(msg.rfind("/quit", 0) == 0)
    {
        string left = color_wrap(get_current_time() + " [Server] " + get_nickname(fd) + " quit.\n", Color::YELLOW);
        broadcast(fd, left);
        send(fd, left.c_str(), left.size(), 0);
        cout << left;
        log_to_file(left);
        FD_CLR(fd, &all_set);
        close(fd);
        room_manager.leave(fd);
        remove_user(fd);
        client_fds.erase(client_fds.begin() + i); 
        --i;
        return;
    }
    else if(msg.rfind("/history", 0) == 0)
    {
        ifstream in("chat_log.txt");
        if(in)
        {
            string line, history;
            while(getline(in, line))
            {
                history += line + "\n";
            }
                string final = "[Chat History]\n-----------------------------\n" + history + "-----------------------------\n";
                final = color_wrap(final, Color::CYAN);
                send(fd, final.c_str(), final.size(), 0);
        }
        return;
    }
    else if(msg.rfind("/kick", 0) == 0)
    {
        istringstream iss(msg);
        string cmd, target_name;
        iss >> cmd >> target_name;
        if(get_nickname(fd) != "admin")
        {
            string err = color_wrap("[Server] Permission denied.\n", Color::RED);
            send(fd, err.c_str(), err.size(), 0);
            return;
        }
        int target_fd = get_fd_by_name(target_name);
        if(target_fd == -1)
        {
            string err = color_wrap("[Server] No such user: " + target_name + "\n.", Color::RED);
            send(fd, err.c_str(), err.size(), 0); return;
        }
        string notice = color_wrap(get_current_time() + " [Server] " + target_name + " was kicked out by " + get_nickname(fd) + ".\n", Color::YELLOW);
        string self_msg = color_wrap(get_current_time() + " [Server] You were kicked out.\n", Color::RED);
        broadcast(target_fd, notice);
        send(target_fd, self_msg.c_str(), self_msg.size(), 0);
        FD_CLR(target_fd, &all_set);
        remove_user(target_fd);
        room_manager.leave(target_fd);
        client_fds.erase(remove(client_fds.begin(), client_fds.end(), target_fd), client_fds.end());
        log_to_file("[Kick] " + get_nickname(fd) + " kicked " + target_name + "\n");
        return;
    }
    else if(msg.rfind("/rename", 0) == 0)
    {
        istringstream iss(msg); string cmd, newname; iss >> cmd >> newname;
        if(newname.empty() || is_nick_name_taken(newname))
        {
            string err = color_wrap("[Server] Invalid or taken name.\n", Color::RED);
            send(fd, err.c_str(), err.size(), 0); return;
        }
        string old = get_nickname(fd);
        set_nickname(fd, newname);
        string notice = color_wrap(get_current_time() + " [Server] " + old + " → " + newname + "\n", Color::YELLOW);
        broadcast(fd, notice);
        send(fd, notice.c_str(), notice.size(), 0);
        log_to_file("[Rename] " + old + " → " + newname + "\n"); return;
    }
    else if(msg.rfind("/room", 0) == 0)
    {
        string output = "[Server] Current active rooms:\n";
        auto all_rooms = room_manager.get_all_rooms();
        if(all_rooms.empty())
        {
            output += " (none)\n";
        }
        else
        {
            for(const auto& [room_name, members] : all_rooms)
            {
                output += " - " + room_name + " (" + to_string(members.size()) + " members)\n";
            }
        }
        string current = room_manager.get_user_room(fd);
        if(current.empty()) current = "(none)";
        output += "\n[Server] You are in room: " + current + "\n";
        string final = color_wrap(output, Color::CYAN);
        send(fd, final.c_str(), final.size(), 0);
    }
    else if(msg.rfind("/leave", 0) == 0)
    {
        string old_room = room_manager.get_user_room(fd);
        string notice = color_wrap(get_current_time() + " [Server] " + get_nickname(fd) + " left room: " + old_room + "\n", Color::YELLOW);
        broadcast(fd, notice);                                                                   
        room_manager.leave(fd);
        string err;
        room_manager.join(fd, "lobby", "", err);
        string self_msg = color_wrap("[Server] You have returned to lobby.\n", Color::CYAN);
        send(fd, self_msg.c_str(), self_msg.size(), 0);
        log_to_file("[Leave] " + get_nickname(fd) + " → lobby\n"); return;
    }
    else if(msg.rfind("/members", 0) == 0)
    {
        string room = room_manager.get_user_room(fd);
        auto fds = room_manager.get_user_room(fd);
        string list = color_wrap("[Room members: " + room + "]\n", Color::CYAN);
        for(int x : fds) list += "- " + get_nickname(x) + "\n";
        send(fd, list.c_str(), list.size(), 0);
        return;
    }
    else if(msg.rfind("/help", 0) == 0)
    {
        string help =
            color_wrap("[Command Help]\n", Color::CYAN) +
            "/who            - Show all online users\n"
            "/room           - Show your current room\n"
            "/members        - List members in your room\n"
            "/join <room> [pwd] - Join or create a room\n"
            "/leave          - Leave current room\n"
            "/rename <name>  - Change your nickname\n"
            "/to <name> msg  - Private message\n"
            "/quit           - Disconnect\n"
            "/kick <user>    - Kick a user (admin only)\n"
            "/help           - Show this help menu\n\n";
        send(fd, help.c_str(), help.size(), 0); return;
    }
    else if(msg.rfind("/who", 0) == 0)
    {
        string list = color_wrap("[Online users]\n", Color::CYAN);
        for (auto& name : get_all_nicknames()) list += "- " + name + "\n";
        send(fd, list.c_str(), list.size(), 0); return;
    }
    else if(msg.rfind("/join", 0) == 0)
    {
        istringstream iss(msg);
        string cmd, room_name, pwd;
        iss >> cmd >> room_name >> pwd;
        if(room_name.empty())
        {
            string err = color_wrap("[Server] Usage: /join <room> [pwd]\n", Color::RED);
            send(fd, err.c_str(), err.size(), 0); return;
        }
        string current = room_manager.get_user_room(fd);
        if(current == room_name)
        {
            string warn = color_wrap("[Server] You are already in room: " + room_name + "\n", Color::YELLOW);
            send(fd, warn.c_str(), warn.size(), 0); return;
        }
        string join_err;
        if(!room_manager.join(fd, room_name, pwd, join_err))
        {
            string err = color_wrap("[Server] " + join_err + "\n", Color::RED);
            send(fd, err.c_str(), err.size(), 0); return;
        }
        string join_msg = color_wrap(get_current_time() + " [Server] " + get_nickname(fd) + " joined room: " + room_name + "\n", Color::GREEN);
        send(fd, join_msg.c_str(), join_msg.size(), 0);
        broadcast(fd, join_msg); log_to_file("[Join] " + get_nickname(fd) + " → " + room_name + "\n"); return;
    }
    else if (msg.rfind("/to", 0) == 0)
    {
        string content = msg.substr(4);
        size_t space = content.find(' ');
        if (space == string::npos)
        {
            string err = color_wrap("[Server] Usage: /to <name> <msg>\n", Color::RED);
            send(fd, err.c_str(), err.size(), 0);
            return;
        }

        string target = content.substr(0, space);
        string real_msg = content.substr(space + 1);

        int target_fd = get_fd_by_name(target);
        if (target_fd == -1)
        {
            string err = color_wrap("[Server] No such user: " + target + "\n", Color::RED);
            send(fd, err.c_str(), err.size(), 0);
            return;
        }

        string from = get_nickname(fd);
        string final_msg = color_wrap(get_current_time() + " [Private from " + from + "] " + real_msg + "\n", Color::CYAN);

        send(target_fd, final_msg.c_str(), final_msg.size(), 0);  // 发给对方
        send(fd, final_msg.c_str(), final_msg.size(), 0);         // 发给自己回显

        log_to_file("[Private] " + from + " → " + target + ": " + real_msg + "\n");
        return;
    }
    else
    {
        string full_msg = color_wrap(
        get_current_time() + " [" + get_nickname(fd) + "] " + msg, Color::RESET);
        broadcast(fd, full_msg);
        cout << full_msg;
        log_to_file(full_msg);
    }





